package com.gome.spiderkit.client;

import java.util.ArrayList;
import java.util.concurrent.TimeoutException;

import com.google.protobuf.InvalidProtocolBufferException;
import com.mongodb.BasicDBList;

public class WebKit {

	static int WKMethodTypeDefault = 0;
	static int WKMethodTypeStaticProtocol = 2;
	static int WKMethodTypeCopyProtocol = 3;
	
	private WebKitMQ m_webkit_mq;
	private ArrayList<String> m_filterRules;
	private String m_method;
	private boolean m_is_static = false;
	private int m_type;
	
	public WebKit (String groupName)
	{
		m_webkit_mq = new WebKitMQ();
		m_filterRules = new ArrayList<String>();
		m_method = groupName;
		m_type = WKMethodTypeDefault;
		m_is_static = false;
		initCaller();
	}
	
	public WebKit (String groupName, boolean isStatic)
	{	
		m_webkit_mq = new WebKitMQ();
		m_filterRules = new ArrayList<String>();
		m_method = groupName;
		m_type = WKMethodTypeDefault;
		m_is_static = isStatic;
		initCaller();
	}
	
	public WebKit (int type, String protocol)
	{
		m_webkit_mq = new WebKitMQ();
		m_filterRules = new ArrayList<String>();
		
		if (!protocol.isEmpty())
			m_method = protocol;
		m_type = type;
		m_is_static = false;
		initCaller();
	}
	
	public WebKit (int type, String protocol, boolean isStatic)
	{
		m_webkit_mq = new WebKitMQ();
		m_filterRules = new ArrayList<String>();
		
		if (!protocol.isEmpty())
			m_method = protocol;
		m_type = type;
		m_is_static = isStatic;
		initCaller();
	}
	
	public WebKit (WebKitMQ mq, WebKit wk)
	{
		m_webkit_mq = mq;
		m_filterRules = new ArrayList<String>();
		
		if (!mq.getProtocol().isEmpty())
			m_method = mq.getProtocol();
		m_type = WKMethodTypeCopyProtocol;
		m_is_static = wk.isStatic();
	}

	public void release()
	{
		this.m_webkit_mq.close();
	}

	public boolean isStatic() {
		return m_is_static;
	}
	
	private void initCaller()
	{
	    if (m_type == WKMethodTypeDefault)
	        m_webkit_mq.initDefault(m_method, m_is_static);
	    else if (m_type == WKMethodTypeStaticProtocol)
	        m_webkit_mq.initWithServerProtocol(m_method);
	}
	
	public boolean isFailed() 
	{
		return m_webkit_mq.failed();
	}
	
	public ArrayList<String> filterRules() {
		return m_filterRules;
	}
	
	public void setFilterRules(ArrayList<String> rules) {
		m_filterRules = rules;
	}
	
	public void setCookies(ArrayList<Cookie> cookies, String url) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException {
		CookieJar jar = new CookieJar(cookies);
		ArrayList<String> argList = new ArrayList<String>();
		argList.add(jar.toJson());
		argList.add(url);
		m_webkit_mq.webKitCall(0, WebKitProtocol.WEBPAGE_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES, argList);
	}
	
	public WebPage get(String url, CookieJar cookies) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, cookies, 100, 120000, -1);
	}
	
	public WebPage get(String url, CookieJar cookies, int loadTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, cookies, 100, loadTimeout, -1);
	}
	
	public WebPage get(String url, CookieJar cookies, int loadTimeout, int deleteTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, cookies, 100, loadTimeout, deleteTimeout);
	}
	
	public WebPage get(String url) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, null, 100, 120000, -1);
	}
	
	public WebPage get(String url,int loadTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, null, 100, loadTimeout, -1);
	}
	
	public WebPage get(String url,int loadTimeout,int deleteTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, null, 100, loadTimeout, deleteTimeout);
	}
	
	public WebPage get(String url,int level,int loadTimeout,int deleteTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		return getWebPage(url, null, level, loadTimeout, deleteTimeout);
	}
	
	public WebPage post(String url, String data) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		WebPage page =  getWebPage(url, null, 100, 120000, -1);
		if (page == null)
			return null;
		
		BasicDBList headers = new BasicDBList();
		if (!page.loadUrl(url, "POST", headers, data, "utf8")) {
			page.destory();
			return null;
		}
		
		return page;
	}

	public WebPage post(String url, String data, int loadTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		WebPage page =  getWebPage(url, null, 100 , loadTimeout, -1);
		if (page == null)
			return null;
		
		BasicDBList headers = new BasicDBList();
		if (!page.loadUrl(url, "POST", headers, data, "utf8")) {
			page.destory();
			return null;
		}
		
		return page;
	}
	
	public WebPage post(String url, String data, int loadTimeout,int deleteTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		WebPage page =  getWebPage(url, null, 100, loadTimeout, deleteTimeout);
		if (page == null)
			return null;
		
		BasicDBList headers = new BasicDBList();
		if (!page.loadUrl(url, "POST", headers, data, "utf8")) {
			page.destory();
			return null;
		}
		
		return page;
	}
	
	public WebPage post(String url, String data, int level, int loadTimeout, int deleteTimeout) throws UnknowServerException, InvalidProtocolBufferException, TimeoutException
	{
		WebPage page =  getWebPage(url, null, level, loadTimeout, deleteTimeout);
		if (page == null)
			return null;
		
		BasicDBList headers = new BasicDBList();
		if (!page.loadUrl(url, "POST", headers, data, "utf8")) {
			page.destory();
			return null;
		}
		
		return page;
	}
	
	public WebPage getWebPage(String url, CookieJar cookies, int level, int loadTimeout, int deleteTimeout) throws InvalidProtocolBufferException, TimeoutException
	{
		
		ArrayList<String> argList = new ArrayList<String>();
		argList.add("0");
		if(url == null || url.isEmpty())
			argList.add("about:blank");
		else
			argList.add(url);
		
		if (cookies != null)
			argList.add(cookies.toJson());
		else
			argList.add("[]");
		
		argList.add(String.valueOf(level));
		argList.add(String.valueOf(loadTimeout));
		
		if (deleteTimeout != -1)
			argList.add(String.valueOf(deleteTimeout));
		
		WebPageRef webpageref = new WebPageRef();
		long ret = -2; 
		int count = 0;
		while(true)
		{
			try {
				int timeOutFix = (deleteTimeout > WebKitMQ.DEFAULT_TIMEOUT ? WebKitMQ.DEFAULT_TIMEOUT : deleteTimeout) / 2;
				String msg = m_webkit_mq.webKitCall(0,WebKitProtocol.WEBKIT_LONG_GET_LONG_REF_STRING_URL, argList, loadTimeout + timeOutFix);
				ret = m_webkit_mq.getPageValue(msg, webpageref);
				if (ret != -2 && ret != -5)
					break;
				
				m_webkit_mq.close();
				m_webkit_mq = null;
				System.gc();
				Thread.sleep(1000);
				m_webkit_mq = new WebKitMQ();
				try {
					initCaller();
				} catch (Exception e) {
					continue;
				}

			} catch (InterruptedException e) {
				continue;
			} catch (UnknowServerException e) {
				continue;
			} finally {
				count++;
				if(count > 10)
					break;
			}
		}
		
		if(ret < 0) {
			WebPage page = new WebPage(m_webkit_mq);
			page.setErrorCode(ret);
			return page;
		}
		
		WebPage page = new WebPage(webpageref.getRef(),m_webkit_mq, this);
		return page;
	}
}
